package com.ctrip.corp.obt.shard.configuration;


import com.ctrip.corp.obt.shard.constants.SourceLoadMode;
import com.ctrip.corp.obt.shard.core.ShardDataSource;
import com.ctrip.corp.obt.shard.sql.mybatis.interceptor.InnerPluginsInterceptor;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Collections;
import java.util.List;

/**
 * @author marco.zheng
 * @version 1.0
 * @date 2022/01/14
 * @description
 * @see
 * @since 1.0
 */
@Data
@ConfigurationProperties(prefix = DataShardProperties.DATA_SHARD_PREFIX)
public class DataShardProperties {

    static final String DATA_SHARD_PREFIX = "arch.shard";

    /**
     * 分片字段，默认为租户id
     */
    private String tenantIdColumn = "tenant_id";

    /**
     * 数据源加载模式
     * 1、全量加载 full (默认)
     * 2、控制面加载 controlPlane
     * 3、single加载 single 只加载默认数据源并屏蔽数据源load接口
     */
    private String sourceLoadMode = SourceLoadMode.FULL.getName();

    /**
     * 不需要进行tenant shard的表
     */
    private List<String> tenantFilterTables;

    /**
     * {@link com.ctrip.corp.obt.shard.handler.strategy.HashTableRouteStrategy} 中使用的参数
     * 根据 {@link DataShardProperties#tenantIdColumn} 进行hash的取值范围，默认为3
     */
    private Integer shardTableRange = 3;

    /**
     * 全局table shard 策略，以下情况下才会使用（如果不配置则不生效）
     * 客户配置并使用 {@link com.ctrip.corp.obt.shard.constants.ShardMode#TABLE} 且没有配置额外的策略
     */
    private String globalTableShardStrategy;

    /**
     * 是否启用cat mybatis拦截器，默认启用
     */
    private boolean enabledCatInterceptor = true;

    /**
     * 是否启用inner plugins拦截器，默认启用，如果设置为false，用户可以自定义组装所需要的Plugin
     * 配置细节可参考{@link InnerPluginsInterceptor#setProperties(java.util.Properties)}
     */
    private boolean enabledInnerPluginsInterceptor = true;

    /**
     * 当不存在sharding_data_source表时，是否自动检测并创建表
     */
    private boolean autoCreateSdsIfNotExist = true;

    /**
     * {@link com.ctrip.corp.obt.shard.context.PageContext} 自定义分页current名称，默认为current
     */
    private String currentParamName;

    /**
     * {@link com.ctrip.corp.obt.shard.context.PageContext} 自定义分页size名称，默认为size
     */
    private String sizeParamName;

    /**
     * 需要权限拦截/过滤的表 白名单（只有在白名单的表需要权限拦截/过滤）
     */
    private List<String> permissionTableWhiteList = Collections.emptyList();

    /**
     * 需要权限拦截/过滤的表 黑名单（只有在白名单的表不做权限拦截/过滤，如果开启了黑名单，则白名单失效）
     */
    private List<String> permissionTableBlackList = Collections.emptyList();

    /**
     * 常见的脱敏类型名称 (拦截匹配这些名称且值带*号的字段更新操作)
     */
    private List<String> commonDesensitizationNames;

    /**
     * 常见的无需拦截的带掩码数据名称 (不拦截匹配这些名称且值带*号的字段更新操作)
     */
    private List<String> commonAllowedMaskNames;

    private List<ShardDataSource> dataSources = Collections.emptyList();

    private static boolean staticEnabledInnerPluginsInterceptor = true;
    private static String staticCurrentParamName = "current";
    private static String staticSizeParamName = "size";

    public boolean isFilterTable(String tableName) {
        if (null == tenantFilterTables) {
            return false;
        }
        return tenantFilterTables.contains(tableName);
    }

    public synchronized void setCurrentParamName(String currentParamName) {
        this.currentParamName = currentParamName;
        staticCurrentParamName = currentParamName;
    }

    public synchronized void setSizeParamName(String sizeParamName) {
        this.sizeParamName = sizeParamName;
        staticSizeParamName = sizeParamName;
    }

    public synchronized void setEnabledInnerPluginsInterceptor(boolean enabledInnerPluginsInterceptor) {
        this.enabledInnerPluginsInterceptor = enabledInnerPluginsInterceptor;
        staticEnabledInnerPluginsInterceptor = enabledInnerPluginsInterceptor;
    }

    public static boolean isEnabledInnerPluginsInterceptor() {
        return staticEnabledInnerPluginsInterceptor;
    }

    public static String currentParamName() {
        return staticCurrentParamName;
    }

    public static String sizeParamName() {
        return staticSizeParamName;
    }
}
